const htmlParser = require('./htmlparse.js');
const utilsConfig = require('./utilsConfig.js');
const OrderTree = require('./OrderTree.js');

const styleReg = /style="([^"]*)"/; // 样式字符串正则
const datasetReg = /data-[A-Za-z0-9-_]+="([^"]*)"/g; // dataset 字符串正则
const srcAttrReg = /src="([^"]*)"/; // src属性字符串正则
const classStrReg = /class="([^"]*)"/g; // 样式类正则

const ignoreOtherAttr = ['powered-by', 'class']; // 直接忽略的其他属性
const ignoreTagStyleMap = new Map([
  ['body', ['height']],
  ['ul', ['width']]
]); // 要忽略指定标签的指定属性
const tagBaseClassMap = new Map([
  ['view', 'parseView'],
  ['image', 'parseImage'],
  ['video', 'parseVideo']
])

let domTree = null; // 节点树
let outerParam = null; // 外部参数（主要是视频地址）

// 获取小程序标签
const getMiniTag = (tagName = '', dom) => {
  if (tagName === 'img') return 'image';
  if (tagName === 'br') return 'br';
  if (tagName === "iframe") {
    let dataset = JSON.parse(dom.dataset);
    if(dataset.mpvid) return 'video';
  }
  if (utilsConfig.blockEleMap.has(tagName)) return 'view';
  if (utilsConfig.inlineEleMap.has(tagName)) return 'text';
}

// 获取必要的tag属性
function setNecessaryAttr(miniTag, rest) {
  if (miniTag === 'image') {
    let match = rest.match(srcAttrReg);
    if (match) {
      this.src = match[1]; return;
    }
  }
  if(miniTag === 'video') {
    let dataset = JSON.parse(this.dataset);
    let other = JSON.parse(this.other);
    this.src = ''; // TODO 添加视频地址
    this.poster = decodeURIComponent(dataset.cover);
    // if(other.width) this.style.width = `${other.width}px`;
    // if(other.height) this.style.height = `${other.height}px`;
  }
}

// 从属性字符串中提取样式文本
const getStyleFromRest = (tagName = '', rest = '') => {
  let style = {};
  let tagBaseStyle = utilsConfig.tagBaseStyleMap.get(tagName);
  if (tagBaseStyle) style = tagBaseStyle;
  let match = rest.match(styleReg);``
  if (match) {
    let styleArr = match[1].split(';');
    for (let i = 0; i < styleArr.length; i += 1) {
      if (styleArr[i]) {
        let styleKeyValueArr = [];
        let firstColonIndex = styleArr[i].indexOf(':');
        styleKeyValueArr.push(styleArr[i].substring(0, firstColonIndex));
        styleKeyValueArr.push(styleArr[i].substring(firstColonIndex + 1));
        let ignoreTag = ignoreTagStyleMap.get(tagName);
        let styleAttrName = styleKeyValueArr[0].replace(/^\s*|\s*$/g, '');
        let styleAttrValue = styleKeyValueArr[1].replace(/^\s*|\s*$/g, '');
        if (ignoreTag) {
          if (ignoreTag.indexOf(styleAttrName) === -1) {
            style[styleAttrName] = styleAttrValue;
          }
        } else {
          style[styleAttrName] = styleAttrValue;
        }
      }
    }
  }
  return style;
}

// 提取样式类字符串
const getClassStr = (rest = '', miniTag = '') => {
  let classStr = tagBaseClassMap.get(miniTag) || '';
  let match = rest.match(classStrReg);
  if(match) {
    classStr += ` ${RegExp.$1}`
  }
  return classStr;
}

// 从属性字符串中获取dataset数据
const getDatasetFromRest = (rest = '') => {
  let dataset = {};
  let match = rest.match(datasetReg);
  if (match) {
    match.forEach(v => {
      let equalSignIndex = v.indexOf('=');
      let tempArr = [
        v.substring(0, equalSignIndex),
        v.substring(equalSignIndex + 1)
      ];
      let key = tempArr[0].substring(tempArr[0].indexOf('-') + 1);
      dataset[key] = tempArr[1].replace(/^"+|"+$/g, '');
    })
  }
  return JSON.stringify(dataset);
}

// 提取其他属性
const getOtherAttrFromRest = (rest = '') => {
  let other = {}, tempRest = rest;
  tempRest = tempRest.trim().replace(styleReg, '').replace(datasetReg, '').replace(classStrReg, '');
  tempRest = tempRest.trim().replace(/\s+/g, '^$');
  if (tempRest) {
    let attrArr = tempRest.split('^$');
    attrArr.forEach(v => {
      let equalSignIndex = v.indexOf('=');
      let tempArr = [
        v.substring(0, equalSignIndex),
        v.substring(equalSignIndex + 1)
      ];
      if (ignoreOtherAttr.indexOf(tempArr[0]) === -1) {
        other[tempArr[0]] = tempArr[1].replace(/^"+|"+$/g, '');
      }
    })
  }
  return JSON.stringify(other);
}

// 节点抽象工厂
const domFactory = ({
  tagName = '', // 标签名
  id = '', // 唯一标识符
  rest, // 属性字符串
} = {}) => {
  let dom = {};
  dom.tagName = tagName;
  dom.id = id;
  dom.dataset = getDatasetFromRest(rest);
  dom.other = getOtherAttrFromRest(rest);
  dom.style = getStyleFromRest(tagName, rest);
  dom.miniTag = getMiniTag(tagName, dom);
  dom.classStr = getClassStr(rest, dom.miniTag);
  dom.innerText = '';
  setNecessaryAttr.call(dom, dom.miniTag, rest);
  return dom;
}

// 添加子节点
const treeAddNode = (data, nodeP) => {
  let newNode = domFactory(data);
  domTree.addNode(newNode, nodeP);
}

// 抛出接口
const scdxParse = ({
  html,
  page,
  param = {},
  onEleClick = () => {}
} = {}) => {
  outerParam = param;
  htmlParser(html, {
    startTag({ tagName, rest, stack, unary, curIndex }) {
      for (let s = 0; s < stack.length; s += 1) { // 忽略svg及所有子节点
        if (stack[s].tagName === 'svg') { return };
      }

      if (unary) { // 一元元素
        let stackP = stack[stack.length - 1];
        let nodeP = stackP ? domTree.getNode(node => {
          if (node) return node.data.id === stackP.id;
        }) : domTree.getRoot();
        treeAddNode({ tagName, id: curIndex, rest }, nodeP);
        return;
      }

      if (!domTree) { // 树还不存在
        domTree = new OrderTree(domFactory({ tagName, id: stack[0].id, rest }));
      } else {
        let stackP = stack[stack.length - 2];
        let stackC = stack[stack.length - 1];
        let nodeP = stackP ? domTree.getNode(node => {
          if (node) return node.data.id === stackP.id;
        }) : domTree.getRoot();
        treeAddNode({ tagName, id: stackC.id, rest }, nodeP);
      }
    },
    endTag({ tagName, stack }) {},
    textTag(text, stack) {
      let stackC = stack[stack.length - 1];
      let nodeC = domTree.getNode(node => node.data.id === stackC.id);
      if (text.length === 1 && text.charCodeAt(text[0]) === 8203) {
        text = '';
      }
      nodeC.data.innerText = nodeC.data.innerText ? nodeC.data.innerText + text : text;
    }
  });


  /* --==============下面开始是进行一系列操作以降低层级 */
  /**
   * 行级标签整合
   */
  const inlineTagIntegration = () => {
    let deep = domTree.deep();
    for (let d = deep; d >= 1; d--) {
      domTree.traverseByDeep(d, (node) => {
        if(node.data.tagName === 'img') return;
        let parent = domTree.getNode(node.parent);
        if (parent && parent.data.innerText === '' && utilsConfig.inlineEleMap.has(parent.data.tagName) && utilsConfig.inlineEleMap.has(node.data.tagName)) { // 行级元素
          parent.data.dataset = JSON.stringify(Object.assign({}, JSON.parse(parent.data.dataset), JSON.parse(node.data.dataset)));
          parent.data.other = JSON.stringify(Object.assign({}, JSON.parse(parent.data.other), JSON.parse(node.data.other)));
          parent.data.style = Object.assign({}, parent.data.style, node.data.style);
          parent.data.innerText = node.data.innerText;
          domTree.singleRemove(node);
        }
      })
    }
  }
  inlineTagIntegration();

  let domList = domTree.getList();
  console.log(domList);
  console.log(domTree.deep());

  // 关联小程序
  // 元素点击事件
  page.onEleClick = (e) => {
    let targetDataset = e.currentTarget.dataset;
    if (targetDataset.dataset !== '{}' || targetDataset.other !== '{}') {
      let param = {};
      if (targetDataset.dataset !== '{}') param.dataset = JSON.parse(targetDataset.dataset);
      if (targetDataset.other !== '{}') param.other = JSON.parse(targetDataset.other);
      onEleClick(param);
    }
  }
  page.setData({ parseData: domList });

}

module.exports = scdxParse;

/**
 * 需要后台处理
 *  1.删除 &#8203; 字符串
 *  2.需要保留的 dataset 数据
 *      data-cover: 视频封面地址
 *      data-src: 图片http地址
 */